package cc.linker.steplink.crm.merchant.task;

import cc.linker.steplink.crm.commons.TradeTypeConstants;
import cc.linker.steplink.crm.commons.constant.WcPayConstant;
import cc.linker.steplink.crm.commons.http.HttpService;
import cc.linker.steplink.crm.commons.lock.RedisLock;
import cc.linker.steplink.crm.commons.model.SystemProperties;
import cc.linker.steplink.crm.commons.model.WcPayProperties;
import cc.linker.steplink.crm.merchant.dao.AssetCenterMapper;
import cc.linker.steplink.crm.merchant.dao.acs.XbMerchantMapper;
import cc.linker.steplink.crm.merchant.pojo.UserAccountPo;
import cc.linker.steplink.crm.merchanth5.dao.acs.PurchaseProcessDao;
import cc.linker.steplink.crm.merchanth5.pojo.acs.ProtectPo;
import cc.linker.steplink.crm.merchanth5.pojo.acs.TradeInfo;
import cc.linker.steplink.crm.merchanth5.service.MallService;
import cc.linker.steplink.crm.merchanth5.service.acs.ProtectRecordService;
import cc.linker.steplink.crm.merchanth5.service.acs.PurchaseProcessService;
import cc.linker.steplink.crm.merchanth5.util.ParamSignUtils;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.net.URISyntaxException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

import static cc.linker.steplink.crm.merchanth5.service.impl.PurchaseProcessServiceImpl.ACS_CREATE_ORDER_INFO;

@Slf4j
@RestController
public class AcsAccountSummaryStatisticsTask {

    @Autowired
    private XbMerchantMapper xbMerchantMapper;
    @Autowired
    private AssetCenterMapper assetCenterMapper;
    @Autowired
    private PurchaseProcessService purchaseProcessService;
    @Autowired
    private PurchaseProcessDao purchaseProcessDao;
    @Autowired
    private HttpService httpService;
    @Autowired
    private WcPayProperties wcPayProperties;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private MallService mallService;
    @Autowired
    private SystemProperties systemProperties;
    @Autowired
    private ProtectRecordService protectRecordService;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 测试接口调用
     *
     * @param day
     */
    public void calcAccountSummarySaler(String day) {
        accountSummarySaler(day);
    }

    @RedisLock("AcsAccountSummaryStatisticsTask_accountSummary")
    @Scheduled(cron = "10 0 0 * * ?")
    public void calcAccountSummary() {
        accountSummary(null);
    }

    /**
     * 机构账单每日汇总
     *
     * @param day
     */
    public void accountSummary(String day) {
        try {
            String statisticsTime;
            if (StringUtils.isEmpty(day)) {
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                Date date = new Date();
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(date);
                calendar.add(Calendar.DAY_OF_MONTH, -1);
                date = calendar.getTime();
                statisticsTime = sdf.format(date);
            } else {
                statisticsTime = day;
            }
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("statisticsTime", statisticsTime);
            // 获取所有机构
            List<String> orgIds = assetCenterMapper.listOrgcode();
            for (String orgId : orgIds) {
                map.put("orgId", orgId);
                if (xbMerchantMapper.ifSummaryStatistics(map) <= 0) {
                    xbMerchantMapper.accountSummaryStatistics(map);
                }
                xbMerchantMapper.updateSummaryStatistics(map);

            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @RedisLock("AcsAccountSummaryStatisticsTask_accountSummarySaler")
    @Scheduled(cron = "15 0 0 * * ?")
    public void calcAccountSummarySaler() {
        accountSummarySaler(null);
    }

    /**
     * 联盟账单每日汇总
     *
     * @param day
     */
    public void accountSummarySaler(String day) {
        try {
            String statisticsTime;
            if (StringUtils.isEmpty(day)) {
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                Date date = new Date();
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(date);
                calendar.add(Calendar.DAY_OF_MONTH, -1);
                date = calendar.getTime();
                statisticsTime = sdf.format(date);
            } else {
                statisticsTime = day;
            }
            Map<String, Object> map = new HashMap<>();
            map.put("statisticsTime", statisticsTime);
            // 获取联盟商家
            List<Map<String, Object>> salerIds = xbMerchantMapper.listAcsSalerIds();
            List<Map<String, Object>> maps = xbMerchantMapper.listDongSalerIds();
            salerIds.addAll(maps);
            for (Map<String, Object> saler : salerIds) {
                map.put("orgId", saler.get("orgId"));
                map.put("salerId", saler.get("salerId"));
                if (xbMerchantMapper.ifSummaryStatisticsSaler(map) <= 0) {
                    xbMerchantMapper.accountSummaryStatisticsSaler0(map);
                }
                xbMerchantMapper.updateSummaryStatisticsSaler(map);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 手动结算
     */
    @GetMapping("/updateAccountMoneyDayTasksToDo")
    @ResponseBody
    public String updateAccountMoneyDayTasksToDo(){
        updateAccountMoneyDayTasks();
        accountSummarySaler(null);
        accountSummary(null);
        return "ok";
    }

    /**
     * 今天解冻金额打到可用余额中
     * 1、查询交易记录今天解冻记录的人与钱
     * 2、更新交易解冻金额及可用余额
     */
    @Async
    @RedisLock("AcsAccountSummaryStatisticsTask_updateAccountMoneyDayTasks")
    @Scheduled(cron = "30 */5 * * * ?")
    public void updateAccountMoneyDayTasks() {
        // 先将t_crm_acs_account_trade_protect维权结束记录插入到t_crm_acs_account_trade中
        this.inserToOld();
        // 需要查出开通和报名
        // 查询交易记录今天解冻记录的人与钱(orderSn)
        List<UserAccountPo> accountListOrder = xbMerchantMapper.selectUnfreezeUserList();
        if (accountListOrder != null && accountListOrder.size() > 0) {
            // 通知通联金额下发
            this.beforeAgentPay(accountListOrder);
            if(systemProperties.isWxSplit()){
                // 微信分账接口
                this.wxSplitAccount(accountListOrder);
            }
            // 更新用户账单
            StringBuilder accountSb = new StringBuilder();
            for (UserAccountPo userAccountPo : accountListOrder) {
                if(userAccountPo.getType().equals(TradeTypeConstants.TRADE_SERVER_FEE)
                   || userAccountPo.getType().equals(TradeTypeConstants.REJUVENATE_FEE)
                   || userAccountPo.getType().equals(TradeTypeConstants.PURCHASE_FEE)
                   || userAccountPo.getType().equals(TradeTypeConstants.SPREAD_FEE)){
                    //交易手续费,返润佣金 要扣除余额（冻结金额没有加），采购要减,推广佣金
                    LOGGER.info("交易类型："+userAccountPo.getType()+"  交易角色："+ userAccountPo.getPayRole());
                    if (userAccountPo.getPayRole() == 1) {
                        xbMerchantMapper.reduceOrgAccountInfoByOrgId(userAccountPo);
                    } else if (userAccountPo.getPayRole() == 2) {
                        // 小B
                        xbMerchantMapper.reduceXbAccountInfoByCid(userAccountPo);
                        stringRedisTemplate.delete("home:customer_info_" + userAccountPo.getCustomerId());
                    }

                }
                if (userAccountPo.getReceiveRole() == 1) {
                    xbMerchantMapper.updateOrgAccountInfoByOrgId(userAccountPo);
                } else if (userAccountPo.getReceiveRole() == 2) {
                    // 小B
                    xbMerchantMapper.updateXbAccountInfoByCid(userAccountPo);
                    stringRedisTemplate.delete("home:customer_info_" + userAccountPo.getCustomerId());
                } else if (userAccountPo.getReceiveRole() == 4) {
                    // 推广员
                    xbMerchantMapper.updateAgentAccountInfoByCid(userAccountPo);
                    stringRedisTemplate.delete("home:customer_info_" + userAccountPo.getCustomerId());
                } else if (userAccountPo.getReceiveRole() == 5) {
                    // 个人
                    xbMerchantMapper.updateAccountInfoByCid(userAccountPo);
                    stringRedisTemplate.delete("home:customer_info_" + userAccountPo.getCustomerId());
                } else {
                    LOGGER.warn("无需解冻" + userAccountPo);
                }
                accountSb.append(userAccountPo.getId());
                accountSb.append(",");
            }
            LOGGER.info("thawMoney" + accountListOrder);
            //更新账单状态
            xbMerchantMapper.updateTradeInfoThawStatus(accountSb.toString());
        } else {
            LOGGER.info("没有需要解冻的金额");
        }
        // 需要查出开通和报名
        // 积分解冻
        List<UserAccountPo> scoreUserList = xbMerchantMapper.selectUnfreezeScoreUserList();
        if (scoreUserList != null && scoreUserList.size() > 0) {
            StringBuilder scoreSb = new StringBuilder();
            for (UserAccountPo userAccountPo : scoreUserList) {
                if (userAccountPo.getType() == 1) {
                    // 积分解冻
                    xbMerchantMapper.unfreezeScoreByCid(userAccountPo);
                } else if (userAccountPo.getType() == 0) {
                    // 积分购买商品，解冻余额
//                    if (userAccountPo.getReceiveRole() == 1) {
//                        // 大B
//                        xbMerchantMapper.updateOrgAccountInfoByOrgId(userAccountPo);
//                    } else if (userAccountPo.getReceiveRole() == 2) {
//                        // 小B
//                        xbMerchantMapper.updateXbAccountInfoByCid(userAccountPo);
//                        stringRedisTemplate.delete("home:customer_info_" + userAccountPo.getCustomerId());
//                    }
                }
                scoreSb.append(userAccountPo.getId());
                scoreSb.append(",");
            }
            LOGGER.info("thawScore" + scoreUserList);
            xbMerchantMapper.updateTradeScoreInfoThawStatus(scoreSb.toString());
        } else {
            LOGGER.info("没有需要解冻的积分");
        }
    }

    /**
     * 报名活动金额解冻
     */
    public void enrollUnfreeze(String msg) {
        List<TradeInfo> tradeInfoList = JSON.parseArray(msg, TradeInfo.class);
        for (TradeInfo tradeInfo : tradeInfoList) {
            UserAccountPo userAccountPo = new UserAccountPo();
            userAccountPo.setBalance(tradeInfo.getAmount().doubleValue());
            userAccountPo.setCustomerId(tradeInfo.getTo());
            if (tradeInfo.getPayType() == 1) {
                if (tradeInfo.getReceiveRole() == 1) {
                    // 大B
                    xbMerchantMapper.updateOrgAccountInfoByOrgId(userAccountPo);
                } else if (tradeInfo.getReceiveRole() == 2) {
                    // 小B
                    xbMerchantMapper.updateXbAccountInfoByCid(userAccountPo);
                } else if (tradeInfo.getReceiveRole() == 4) {
                    // 推广员
                    xbMerchantMapper.updateAgentAccountInfoByCid(userAccountPo);
                } else if (tradeInfo.getReceiveRole() == 5) {
                    // 个人
                    xbMerchantMapper.updateAccountInfoByCid(userAccountPo);
                } else {
                    LOGGER.warn("无需解冻" + tradeInfo);
                }
            } else {
                xbMerchantMapper.unfreezeScoreByCid(userAccountPo);
            }
        }
    }

    /**
     * 微信分账
     *
     * @param msg orderSn
     */
    public void wxSplitAccountMq(String msg) {
        try {
            if (!systemProperties.isWxSplit()) {
                return;
            }
            LOGGER.info("begin==wxSplitAccountMq===msg===[{}]", msg);
            if (StringUtils.isEmpty(msg)) {
                return;
            }
            // todo 根据orderSn 查出accountList
            List<UserAccountPo> accountList = new ArrayList<>();
            UserAccountPo userAccountPo = new UserAccountPo();
            userAccountPo.setReceiveRole(1);
            userAccountPo.setOrderSn(msg);
            accountList.add(userAccountPo);
            UserAccountPo userAccountPo2 = new UserAccountPo();
            userAccountPo2.setReceiveRole(2);
            userAccountPo2.setOrderSn(msg);
            accountList.add(userAccountPo2);
            //
            // 添加分账接收方
            this.wxSplitAccountStepOne(accountList);
            // 订单分账
            this.wxSplitAccountStepTwo(accountList);
        } catch (Exception e) {
            LOGGER.error("wxSplitAccountMq Exception", e);
        }
    }

    @Async
    public void wxSplitAccount(List<UserAccountPo> accountList) {
        if (!systemProperties.isWxSplit()) {
            return;
        }
        LOGGER.info("wxSplitAccount,start");
        // 添加分账接收方
        this.wxSplitAccountStepOne(accountList);
        // 订单分账
        this.wxSplitAccountStepTwo(accountList);
    }

    private void wxSplitAccountStepOne(List<UserAccountPo> accountList) {
        for (UserAccountPo userAccountPo : accountList) {
            // account	        分账接收方帐号	string	类型是MERCHANT_ID时，是商户ID 类型是PERSONAL_WECHATID时，是个人微信号 类型是PERSONAL_OPENID时，是个人openid 类型是PERSONAL_SUB_OPENID时，是个人sub_openid
            // appSign	        参数签名	string
            // custom_relation	子商户与接收方具体的关系，本字段最多10个字	string	当字段relation_type的值为CUSTOM时，本字段必填 当字段relation_type的值不为CUSTOM时，本字段无需填写
            // name	            分账接收方全称	string	分账接收方类型是MERCHANT_ID时，是商户全称（必传） 分账接收方类型是PERSONAL_NAME 时，是个人姓名（必传） 分账接收方类型是PERSONAL_OPENID时，是个人姓名（选传，传则校验） 分账接收方类型是PERSONAL_SUB_OPENID时，是个人姓名（选传，传则校验）
            // relation_type	子商户与接收方的关系	string	SERVICE_PROVIDER：服务商 STORE：门店 STAFF：员工 STORE_OWNER：店主 PARTNER：合作伙伴 HEADQUARTER：总 BRAND：品牌方 DISTRIBUTOR：分销商 USER：用户 SUPPLIER：供应商 CUSTOM：自定义
            // type	            分账接收方类型	string	MERCHANT_ID：商户ID; PERSONAL_WECHATID：个人微信号 ; PERSONAL_OPENID：个人openid（由父商户APPID转换得到）; PERSONAL_SUB_OPENID: 个人sub_openid（由子商户APPID转换得到）
            // wcpayType	    微信支付标识(支付网关后台添加微信支付信息后生成)	string

            Map<String, String> map = new HashMap<>();
            String account = "";
            String name = "";
            String relationType = "";
            String  type = "";
            if (userAccountPo.getReceiveRole() == 1) {
                account = "1562049721";
                name = "云听晓汇";
                relationType = "SERVICE_PROVIDER";
                type = "MERCHANT_ID";
            }else {
                account = "oD-v-jpqb2l9Z4ksh_HeAHLnHBVk";
                name = "晓风残月几重";
                relationType = "USER";
                type = "PERSONAL_SUB_OPENID";
            }


            // 收款人
//            userAccountPo.getCustomerId();
            String orderSn = userAccountPo.getOrderSn();
            Map<String, Object> orderInfo = purchaseProcessDao.getOrderInfoByOrderSn(orderSn);
//            List<Map<String, Object>> orderInfo = purchaseProcessDao.getOrderInfoByPaySn(orderSn);
            if (null == orderInfo || orderInfo.size()==0) {
                continue;
            }
            String orgId = (String) orderInfo.get("orgId");
            Integer payMode = mallService.getPayModeByOrgId(orgId);
            if (payMode != 1) {
                continue;
            }
            map.put("account", account);
            map.put("custom_relation", "");
            map.put("name", name);
            map.put("relation_type", relationType);
            map.put("type", type);
            String wcpayType = "STEPLINK_" + orgId;
            map.put("wcpayType", wcpayType);
            Map<String, String> appSign = ParamSignUtils.sign(map);
            map.put("appSign", appSign.get("appSign"));
            String url = wcPayProperties.getPayurl() + WcPayConstant.PAY_WCPAY_PROFITSHARINGADDRECEIVER;
            String result;
            try {
                LOGGER.info("wxSplitAccountStepOne,request===[{}]", map);
                result = httpService.doPost(url, new HashMap<>(map));
            } catch (URISyntaxException | IOException e) {
                LOGGER.error("网关调用异常");
                continue;
            }
            LOGGER.info("wxSplitAccountStepOne,result===[{}]", result);

            try {
                Thread.sleep(1000);
            } catch (InterruptedException ignored) {

            }
        }
    }

    private void wxSplitAccountStepTwo(List<UserAccountPo> accountList) {
        List<String> orderSns = this.getOrderSn(accountList);

        for (String sn : orderSns) {
            // appSign	    参数签名	string
            // outOrderNo	商户分账单号，系统确保唯一	string
            // outTradeNo	原微信支付订单(平台的）	string
            // receivers	分账列表，json字符串	string
            // wcpayType	微信支付标识(支付网关后台添加微信支付信息后生成)	string

            Map<String, Object> orderInfo = purchaseProcessDao.getOrderInfoByOrderSn(sn);
//            List<Map<String, Object>> orderInfo = purchaseProcessDao.getOrderInfoByPaySn(sn);
            String orgId = (String) orderInfo.get("orgId");
            Integer payMode = mallService.getPayModeByOrgId(orgId);
            if (payMode != 1) {
                continue;
            }

            //orgId不是空则是商品,获取支付paysn
            String paySn =  purchaseProcessDao.getPaySnByOrderSn(sn);

            Map<String, String> map = new HashMap<>();
            String uid = UUID.randomUUID().toString();
            LOGGER.info("uid===[{}]", uid);
            map.put("outOrderNo", uid);
            map.put("outTradeNo", paySn);


            String receivers = this.getReceiversByTradeInfo(sn);
            map.put("receivers", receivers);

            String wcpayType = "STEPLINK_" + orgId;
            map.put("wcpayType", wcpayType);
            Map<String, String> appSign = ParamSignUtils.sign(map);
            map.put("appSign", appSign.get("appSign"));
            String url = wcPayProperties.getPayurl() + WcPayConstant.PAY_WCPAY_MULTIPROFITSHARING;
            String result;
            try {
                LOGGER.info("wxSplitAccountStepTwo,request===[{}]", map);
                result = httpService.doPost(url, new HashMap<>(map));
            } catch (URISyntaxException | IOException e) {
                LOGGER.error("网关调用异常");
                continue;
            }
            LOGGER.info("wxSplitAccountStepTwo,result===[{}]", result);

            try {
                Thread.sleep(1000);
            } catch (InterruptedException ignored) {

            }
        }
    }

    private String getReceiversByTradeInfo(String sn) {
        // info 中 推荐费接收用户需要更新
        String info = redisTemplate.opsForValue().get(ACS_CREATE_ORDER_INFO + sn);
        if (StringUtils.isEmpty(info)) {
            LOGGER.warn("订单已过期或无账单信息,orderSn===[{}]", sn);
//            return null;
        }
//        List<TradeInfo> tradeInfoList = JSON.parseArray(info, TradeInfo.class);
        List<TradeInfo> tradeInfoList = new ArrayList<>();
        TradeInfo tradeInfo1 = new TradeInfo();
        tradeInfo1.setAmount(1);
        tradeInfo1.setTo("MERCHANT_ID");
        tradeInfo1.setFrom("1562049721");
        tradeInfo1.setAccountType("分到商户");
        tradeInfoList.add(tradeInfo1);
        TradeInfo tradeInfo2 = new TradeInfo();
        tradeInfo2.setAmount(1);
        tradeInfo2.setTo("PERSONAL_SUB_OPENID");
        tradeInfo2.setFrom("oD-v-jpqb2l9Z4ksh_HeAHLnHBVk");
        tradeInfo2.setAccountType("分到个人");
        tradeInfoList.add(tradeInfo2);

        List<Map<String, Object>> resultList = new ArrayList<>();
        for (TradeInfo tradeInfo : tradeInfoList) {
            Map<String, Object> resultMap = new HashMap<>();
            //    "type": "MERCHANT_ID",
            //    "account": "190001001",
            //    "amount": 100,
            //    "description": "分到商户"
            resultMap.put("type", tradeInfo.getTo());
            resultMap.put("account", tradeInfo.getFrom());
            resultMap.put("amount", tradeInfo.getAmount());
            resultMap.put("description", tradeInfo.getAccountType());
            resultList.add(resultMap);
        }
        return JSON.toJSONString(resultList);
    }

    @Async
    public void beforeAgentPay(List<UserAccountPo> accountList) {
        List<String> collect = this.getOrderSn(accountList);
        String join = org.apache.commons.lang.StringUtils.join(collect, ",");
        purchaseProcessService.signalAgentPay(join, "");
    }

    private List<String> getOrderSn(List<UserAccountPo> accountList) {
        return accountList.stream()
                .map(x -> x.getOrderSn().split(","))
                .flatMap(Arrays::stream)
                .distinct()
                .collect(Collectors.toList());
    }


    /**
     * 账单新表入老表
     */
    public void inserToOld() {
        // 查询完结订单号
        List<String> orderSnList = protectRecordService.getOrderSnList();
        // 根据订单号进行结算
        if (orderSnList != null && orderSnList.size() > 0) {
            for (String orderSn : orderSnList) {
                LOGGER.info("结算中心入账开始 orderSn--->" + orderSn);
                List<ProtectPo> protectList = protectRecordService.settleOrder(orderSn);
                if (protectList != null && protectList.size() > 0) {
                    protectRecordService.insertOldTrder(protectList);
                    //判断订单是否是开通会员订单
                    if(!StringUtils.isEmpty(orderSn)){
                        boolean isVipOrder = orderSn.startsWith("V");
                        if(isVipOrder){
                            protectRecordService.doneVipOrder(orderSn);
                        }else{
                            //订单结算完推送消息
//                            amqpTemplate.convertAndSend(QueueName.ORDER_SUMMARY_END, orderSn);
                        }
                    }
                    //更新新表的isEnd状态
                    LOGGER.info("结算中心入账完成 orderSn--->" + orderSn);
                    protectRecordService.updateIsEnd(orderSn, 1);
                    if(orderSn.startsWith("I")){
                        //积分商品
                        protectRecordService.updateIntegralOrderIsEnd(orderSn, 1);
                    }else {
                        protectRecordService.updateOrderIsEnd(orderSn, 1);
                    }
                } else {
                    //更新新表的isEnd状态
                    protectRecordService.updateIsEnd(orderSn, 2);
                    protectRecordService.updateOrderIsEnd(orderSn, 1);
                }

            }
        }
    }

}
